/***************************************************************************
 *   KShootout - online shootout card game.                                *
 *   Copyright (C) 2008, 2009  MacJariel                                   *
 *                                                                         *
 *   KShootout is free software: you can redistribute it and/or modify     *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation, either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   KShootout is distributed in the hope that it will be useful,          *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with KShootout.  If not, see <http://www.gnu.org/licenses/>.    *
 ***************************************************************************/
#include "playerwidget.h"
#include "characterwidget.h"
#include "game.h"
#include "gameactionmanager.h"
#include "cardlistwidget.h"
#include "config.h"

#include <QPainter>
#include <QMouseEvent>


using namespace client;

PlayerWidget::PlayerWidget(QWidget* parent):
        QWidget(parent),
        mp_playerData(0),
        m_isCurrent(0),
        m_isRequested(0),
        mp_winnerIcon(0)
{
}

PlayerWidget::~PlayerWidget()
{
    delete mp_playerData;
}

PlayerId PlayerWidget::id() const
{
    return isVoid() ? 0 : mp_playerData->id;
}

QString PlayerWidget::name() const
{
    return isVoid() ? QString() : mp_playerData->name;
}

PlayerRole PlayerWidget::role() const
{
    return isVoid() ? ROLE_INVALID : mp_playerData->role;
}

bool PlayerWidget::isAlive() const
{
    return isVoid() ? 0 : mp_playerData->isAlive;
}

bool PlayerWidget::isWinner() const
{
    return isVoid() ? 0 : mp_playerData->isWinner;
}

void PlayerWidget::setFromPlayerData(const PlayerData& playerData)
{
    delete mp_playerData;
    mp_playerData = new PlayerData(playerData);
    updateWidgets();
}

void PlayerWidget::clear()
{
    delete mp_playerData;
    mp_playerData = 0;
    updateWidgets();
}

void PlayerWidget::setCurrent(bool isCurrent)
{
    m_isCurrent = isCurrent;
}

void PlayerWidget::setRequested(bool isRequested)
{
    m_isRequested = isRequested;
}

/* virtual */
void PlayerWidget::updateWidgets()
{
    if (isVoid()) {
        // clear player's name
        playerNameLabel()->setText("");

        // clear player's avatar
        avatarLabel()->setPixmap(QPixmap());

        // clear character widget
        characterWidget()->setCharacter("");

        // clear hand widget
        handWidget()->clear();

        // clear table widget
        tableWidget()->clear();

        // clear winner icon
        delete mp_winnerIcon;
    } else {
        // update player's name
        /// @todo escape player name
        playerNameLabel()->setText(mp_playerData->name);

        // update player's avatar
        updateAvatarLabel();

        // update character widget
        characterWidget()->setCharacter(mp_playerData->character);
        characterWidget()->setLifePoints(mp_playerData->lifePoints);
        characterWidget()->setOwnerId(mp_playerData->id);

        // update hand widget
        handWidget()->setOwnerId(mp_playerData->id);
        if (mp_playerData->hasFlag(PlayerData::HandAttr)) {
            // PlayerData contains cards in hand
            setCardListRevealed(handWidget(), mp_playerData->hand);
        } else if (mp_playerData->hasFlag(PlayerData::HandSizeAttr)) {
            // PlayerData only contains hand size
            setCardListUnrevealed(handWidget(), mp_playerData->handSize);
        } else {
            // PlayerData does not contain no information about cards in hand
            qWarning("[PlayerWidget] Trying to update PlayerWidget with PlayerData "
            "that does not contain information about cards in hand.");
            handWidget()->clear();
        }

        // update table widget
        tableWidget()->setOwnerId(mp_playerData->id);
        setCardListUnrevealed(tableWidget(), mp_playerData->table);

        // update winner icon
        if (mp_playerData->isWinner && mp_winnerIcon == 0) {
            createWinnerIcon();
        } else {
            delete mp_winnerIcon;
        }
    }
}

/* virtual */
void PlayerWidget::paintEvent(QPaintEvent* event)
{
    QPainter painter(this);
    painter.setClipRect(event->rect());
    painter.fillRect(contentsRect(), QColor(0, 0, 0, 32));

    if (m_isCurrent) {
        painter.setPen(Qt::blue);
        painter.drawRect(contentsRect().adjusted(0, 0, -1, -1));
    }

    if (m_isRequested) {
        QPen pen;
        pen.setColor(Qt::red);
        pen.setWidth(2);
        pen.setStyle(Qt::DashLine);
        painter.setPen(pen);
        painter.drawRect(rect().adjusted(1, 1, -2, -2));
    }
}

/* virtual */
void PlayerWidget::mousePressEvent(QMouseEvent* event)
{
    Game* currentGame = Game::currentGame();
    if (currentGame) {
        GameActionManager* actionManager = currentGame->actionManager();
        if (event->button() == Qt::LeftButton) {
            actionManager()->onPlayerClicked(this);
        }
    }
}

void PlayerWidget::setCardListRevealed(CardListWidget* cardListWidget,
                                       const CardListData& cardListData)
{
    cardListWidget->clear();
    foreach (const CardData& cardData, cardListData) {
        CardWidget* cardWidget = new CardWidget(this);
        cardWidget->setCardData(cardData);
        cardWidget->updatePixmap();
        cardListWidget->push(cardWidget);
    }
}

void PlayerWidget::setCardListUnrevealed(CardListWidget* cardListWidget,
                                         quint8 cardCount)
{
    cardListWidget->clear();
    for (int i = 0; i < cardCount; ++i) {
        CardWidget* cardWidget = new CardWidget(this);
        cardWidget->cardData().type = CARDTYPE_PLAYING;
        cardWidget->updatePixmap();
        cardListWidget->push(cardWidget);
    }
}

void PlayerWidget::updateAvatarLabel()
{
    ///@todo rewrite avatars using AvatarId and cached AvatarCache
    ///Idea: there could be a class AvatarWidget that would accept AvatarId
    ///      and it would transparently communicate with AvatarCache, that would
    ///      provide avatar data through quering the server. All would be connected
    ///      with signals, so we would only set new AvatarId and avatar would reload
    ///      transparently.
#if 0
    QPixmap avatar = m_avatar;
    if (!m_hasController && !avatar.isNull()) {
        QPainter painter(&avatar);
        painter.fillRect(avatar.rect(), QColor(0, 0, 0, 128));
    }
    avatarLabel()->setPixmap(avatar);
#endif
}

void PlayerWidget::createWinnerIcon()
{
    Q_ASSERT(mp_winnerIcon == 0);
    QPixmap winnerPixmap(Config::systemDataLocation() + "gfx/misc/winner-sign.png");
    mp_winnerIcon = new QLabel(this);
    mp_winnerIcon->setPixmap(winnerPixmap);
    mp_winnerIcon->resize(winnerPixmap.size());
    mp_winnerIcon->setToolTip(tr("This player is winner."));
    mp_winnerIcon->show();
    mp_winnerIcon->raise();
}

// Deprecated:
#if 0
GameActionManager*
PlayerWidget::gameActionManager() const
{
    if (mp_game == 0) {
        return 0;
    } else {
        return mp_game->actionManager();
    }
}
#endif